package server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.InputMismatchException;
import java.util.NoSuchElementException;
import java.util.Scanner;

/**
 * Computes incoming requests.
 * 
 * @author Lukas
 *
 */
public class Handler implements Runnable {
	private final Socket socket;
	private final NetworkService service;
	private String user = null;
	private boolean running;
	
	/**
	 * Creator
	 * @param socket The socket.
	 * @param service The service.
	 */
	public Handler(Socket socket, NetworkService service) {
		this.socket = socket;
		this.service = service;
		running = true;
	}

	@Override
	public void run() {
		BufferedReader in = null;
		PrintWriter out;
		try {
			in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
	        out = new PrintWriter(socket.getOutputStream(), true);
		} catch (IOException e) {
			System.err.println("Could not create I/O");
			if (in != null) {
				try {
					in.close();
				} catch (IOException e1) {
					System.err.println("Could not close input reader");
				}
			}
			return;
		}
		
		String input;
		try {
			while (running && (input = in.readLine()) != null) {
				try {
					out.println(processInput(input));
				} catch (IllegalArgumentException e) {
					out.println("Illegal argument!\n!eof");
				} catch (InputMismatchException e) {
					out.println("Illegal argument!\n!eof");
				} catch (NoSuchElementException e) {
					out.println("Not enough arguments!\n!eof");
				}
				if (user == null) {
					out.println("");
				} else {
					out.println(user + ">: ");
				}
			}
		} catch (IOException e) {
			System.err.println("Shutting down connection");
		}
		
		try {
			in.close();
		} catch (IOException e) {
			System.err.println("Could not close socket input");
		}
		try {
			socket.close();
		} catch (IOException e) {
			System.err.println("Could not close socket");
		}
		
		synchronized (service.handlerList) {
			if (!service.handlerList.remove(this)) {
				System.err.println("Could not remove handler from list of active handlers");
			}
		}
	}
	
	private String processInput(String input) {
		final String loginMessage = "You have to log in first!";
		Scanner sc = new Scanner(input);
		String command = sc.next();
		String response = "unknown command";
		if (command.equals("!login")) {
			if (user != null) {
				response = user + "\nYou have to logout first!";
			} else {
				String userName = sc.next();
				if (service.login(userName, socket, sc.nextInt())) {
					user = userName;
					response = user + "\nsuccessfully logged in as " + user + "!";
				} else {
					response = "\n" + userName + " is already logged in!";
				}
			}
		}
		if (command.equals("!logout")) {
			if (user == null) {
				response = loginMessage;
			} else {
				response = logout();
			}
		}
		if (command.equals("!end")) {
			if (user != null) {
				service.logout(user);
				user = null;
			}
			response = "Shutting down connection.";
			running = false;
		}
		
		if (command.equals("!create")) {
			if (user == null) {
				response = loginMessage;
			} else {
				int duration = sc.nextInt();
				response = service.auctionManager.newAuction(user, sc.nextLine().trim(), duration);
			}
		}
		if (command.equals("!bid")) {
			if (user == null) {
				response = loginMessage;
			} else {
				int id = sc.nextInt();
				int amount = service.auctionManager.convertPrice(sc.next());
				response = service.auctionManager.newBid(id, amount, user);
			}
		}
		if (command.equals("!list")) {
			response = service.auctionManager.listAuctions();
		}
		return response + "\n!eof";
	}
	
	private String logout() {
		String response;
		if (service.logout(user)) {
			response = "successfully logged out as " + user + "!";
			user = null;
		} else {
			response = "Could not log out!";
		}
		return response;
	}
	
	/**
	 * Stops the handler.
	 */
	public void stop() {
		try {
			socket.close();
		} catch (IOException e) {
			System.err.println("Could not close socket");
		}
	}
}
